package com.example.demo.service.impl;

import com.example.demo.exception.AccessDeniedException;
import com.example.demo.exception.ResourceNotFoundException;
import com.example.demo.model.dto.ChangePasswordDTO;
import com.example.demo.model.dto.ProfileUpdateDTO;
import com.example.demo.mapper.TeacherStudentRelationMapper;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.entity.user.User;
import com.example.demo.model.enums.UserStatus;
import com.example.demo.model.enums.UserTypeEnum;
import com.example.demo.security.AuthenticationFacade;
import com.example.demo.security.SecurityUtils;
import com.example.demo.service.ProfileService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class ProfileServiceImpl implements ProfileService {

    private final UserMapper userMapper;
    private final TeacherStudentRelationMapper relationMapper;
    private final SecurityUtils securityUtils;
    private final PasswordEncoder passwordEncoder;
    private final AuthenticationFacade authenticationFacade;

    @Override
    @Transactional(readOnly = true)
    public User getCurrentUserProfile() {
        String username = securityUtils.getCurrentUsername();
        return userMapper.findByUsername(username)
                .map(user -> {
                    // 防御性检查
                    if (user.getUserId() == null) {
                        throw new IllegalStateException("用户ID不能为空");
                    }
                    if (user.getUserType() == null) {
                        user.setUserType(UserTypeEnum.STUDENT);
                    }
                    return user;
                })
                .orElseThrow(() -> new ResourceNotFoundException("User", "username", username));
    }

    @Override
    @Transactional
    public User updateCurrentUserProfile(ProfileUpdateDTO updateDTO) {
        User user = getCurrentUserProfile();
        validateUserId(user.getUserId());

        Optional.ofNullable(updateDTO.getName()).ifPresent(user::setName);
        Optional.ofNullable(updateDTO.getEmail()).ifPresent(user::setEmail);
        Optional.ofNullable(updateDTO.getPhone()).ifPresent(user::setPhone);
        Optional.ofNullable(updateDTO.getAvatar()).ifPresent(user::setAvatar);

        int updated = userMapper.update(user);
        if (updated == 0) {
            throw new IllegalStateException("更新用户信息失败");
        }

        return userMapper.findByUserId(user.getUserId())
                .orElseThrow(() -> new ResourceNotFoundException("User", "userId", user.getUserId()));
    }

    @Override
    @Transactional
    public void deactivateCurrentUserAccount() {
        User user = getCurrentUserProfile();
        validateUserId(user.getUserId());

        user.setStatus(UserStatus.DISABLED.getCode());
        int updated = userMapper.updateStatus(user.getUserId(), user.getStatus());
        if (updated == 0) {
            throw new IllegalStateException("禁用账户失败");
        }
    }

    @Override
    @Transactional
    public void deleteUserWithPermissionCheck(Long targetUserId) {
        validateUserId(targetUserId);
        User currentUser = getCurrentUserProfile();
        User targetUser = userMapper.findByUserId(targetUserId)
                .orElseThrow(() -> new ResourceNotFoundException("User", "userId", targetUserId));

        // 权限检查逻辑
        if (currentUser.isAdmin()) {
            userMapper.delete(targetUserId);
        }
        else if (currentUser.isTeacher() && targetUser.isStudent()) {
            validateTeacherStudentRelation(currentUser.getUserId(), targetUserId);
            relationMapper.deleteByTeacherIdAndStudentId(currentUser.getUserId(), targetUserId);
            userMapper.delete(targetUserId);
        }
        else if (currentUser.getUserId().equals(targetUserId)) {
            userMapper.delete(targetUserId);
        }
        else {
            throw new AccessDeniedException("无权删除该用户");
        }
    }

    @Override
    @Transactional
    public void changeCurrentUserPassword(ChangePasswordDTO changePasswordDTO) {
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        User user = userMapper.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("用户不存在"));
        validateUserId(user.getUserId());

        // 密码验证逻辑
        validatePasswordChange(user, changePasswordDTO);

        String encodedPassword = passwordEncoder.encode(changePasswordDTO.getNewPassword());
        int updated = userMapper.updatePassword(user.getUserId(), encodedPassword);
        if (updated == 0) {
            throw new IllegalStateException("密码更新失败");
        }
    }

    @Override
    @Transactional(readOnly = true)
    public PageInfo<User> getAllUsers(int pageNum, int pageSize) {
        User currentUser = authenticationFacade.getCurrentUser();
        if (!UserTypeEnum.ADMIN.equals(currentUser.getUserType())) {
            throw new AccessDeniedException("需要管理员权限");
        }

        // 使用 PageHelper 开启分页
        PageHelper.startPage(pageNum, pageSize);

        // 执行查询，PageHelper 会自动拦截并添加分页逻辑
        List<User> users = userMapper.findAll();

        // 将结果封装到 PageInfo 中，包含分页信息
        return new PageInfo<>(users);
    }

    @Override
    public List<User> searchUsers(String keyword) {
        User currentUser = authenticationFacade.getCurrentUser();
        if (!UserTypeEnum.ADMIN.equals(currentUser.getUserType())) {
            throw new AccessDeniedException("需要管理员权限");
        }

        return userMapper.searchByUsernameOrName(keyword);
    }

    // ============= 私有方法 =============
    private void validateUserId(Long userId) {
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
    }

    private void validateTeacherStudentRelation(Long teacherId, Long studentId) {
        if (!relationMapper.existsByTeacherIdAndStudentId(teacherId, studentId)) {
            throw new AccessDeniedException("只能删除关联的学生");
        }
    }

    private void validatePasswordChange(User user, ChangePasswordDTO dto) {
        if (!passwordEncoder.matches(dto.getCurrentPassword(), user.getPassword())) {
            throw new IllegalArgumentException("当前密码不正确");
        }
        if (!dto.getNewPassword().equals(dto.getConfirmPassword())) {
            throw new IllegalArgumentException("密码确认不匹配");
        }
        if (passwordEncoder.matches(dto.getNewPassword(), user.getPassword())) {
            throw new IllegalArgumentException("新密码不能与旧密码相同");
        }
    }
}